<style scoped lang="scss">
.svg-in-rect {
    width: 18px;
    padding: 0 2px 0 8px;
}

.node {
    display: flex;
    align-items: center;
    width: calc(100% - 4px);
    height: 100%;
    background-color: #fff;
    border: 1px solid #c2c8d5;
    border-left: 4px solid #5F95FF;
    border-radius: 4px;
    box-shadow: 0 2px 5px 1px rgba(0, 0, 0, 0.06);
    cursor: pointer;
    transition: all 0.3s ease;
}

.node img {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    margin-left: 6px;
}

.node .label {
    display: inline-block;
    flex-shrink: 0;
    width: 120px;
    word-wrap: break-word;
    word-break: break-all;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
    margin-left: 4px;
    color: #666;
    font-size: 12px;
}

// transparent circle background
.svgnode {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    transition: all 0.3s ease;
}

// make it look like a round rected bigger highlighted card, with transition(only for scale)
// make it expand
.svgnode.highlight {
    // background-color: #fff;
    border: 1px solid #1890ff;
    border-radius: 4px;
    box-shadow: 0 2px 5px 1px #5F95FF;
    transform: scale(1.2);
    transition: all ease 0.3s;
}

.svgnode.preHighlight {
    // background-color: #fff;
    border: 1px solid #52c41a;
    border-radius: 4px;
    box-shadow: 0 2px 5px 1px #8dd3b4;
    transform: scale(1.2);
    transition: all ease 0.3s;
}

.node .status {
    flex-shrink: 0;
}

.node.success {
    border-left: 4px solid #52c41a;
}

.node.failed {
    border-left: 4px solid #ff4d4f;
}

.node.running .status img {
    animation: spin 1s linear infinite;
}

.node.highlight {
    border-color: #1890ff;
    border-radius: 2px;
    box-shadow: 0 0 0 4px #d4e8fe;
    transform: scale(1.1);
    transition: all ease 0.3s;
}

.node.preHighlight {
    border-color: #52c41a;
    border-radius: 2px;
    box-shadow: 0 0 0 4px #d6fff8;
    transform: scale(1.1);
    transition: all ease 0.3s;
}

.x6-node-selected .node {
    border-color: #1890ff;
    border-radius: 2px;
    box-shadow: 0 0 0 4px #d4e8fe;
}

.x6-node-selected .node.success {
    border-color: #52c41a;
    border-radius: 2px;
    box-shadow: 0 0 0 4px #ccecc0;
}

.x6-node-selected .node.failed {
    border-color: #ff4d4f;
    border-radius: 2px;
    box-shadow: 0 0 0 4px #fedcdc;
}

.x6-edge:hover path:nth-child(2) {
    stroke: #1890ff;
    stroke-width: 1px;
}

.x6-edge-selected path:nth-child(2) {
    stroke: #1890ff;
    stroke-width: 1.5px !important;
}

@keyframes running-line {
    to {
        stroke-dashoffset: -1000;
    }
}

@keyframes spin {
    from {
        transform: rotate(0deg);
    }

    to {
        transform: rotate(360deg);
    }
}
</style>

<!-- ts项目使用js组件 -->
<script lang="jsx">
import { render } from 'vue';
import { LayoutMode } from '../../../algorithm/dag-layout';

export default {
    name: "GraphNode",
    inject: ["getGraph", "getNode"],
    render() {
        const { label, status, type, nodeType, layoutMode } = this.getNode().getData()
        this.status = status || this.status
        const labelOffset = (string) => {
            // for chinese characters, length += 2
            let length = 0
            for (let i = 0; i < string.length; i++) {
                if (string.charCodeAt(i) > 255) {
                    length += 2
                } else {
                    length += 1
                }
            }
            if (length < 10) {
                return -length * 1;
            } else if (length < 20) {
                return length * 1;
            } else if (length < 30) {
                return length * 2;
            } else {
                return length * 2.2;
            }
        }
        return nodeType === 'rect' ? (
            <div className={`node ${this.status}`} onMouseenter={this.hignlightNodeEdge} onMouseleave={this.restoreNodeEdge}>
                <svg class="svg-in-rect">
                    <use href={`#svg-icon-${type}`}></use>
                </svg>
                <span className="label" title={label}>{label}</span>
            </div>
        ) : (
            <div className={`svgnode ${this.status}`} style="width: 100%; height: 100%" onMouseenter={this.hignlightNodeEdge} onMouseleave={this.restoreNodeEdge}>
                <svg style="width: 100%; height: 100%;z-index:-1" >
                    <use href={`#svg-icon-${type}`}></use>
                </svg>
                {
                    layoutMode === LayoutMode.Horizontal ?
                        <span style={{ 'color': '#666', 'font-size': '10px', 'white-space': 'nowrap', 'margin-left': -labelOffset(label) + 'px' }}>{label}</span>
                        :
                        <span style={{ 'color': '#666', 'font-size': '10px', 'white-space': 'nowrap', 'position': 'absolute', 'left': '60px', 'top': '12px' }}>{label}</span>
                }
            </div>
        )
    },
    data() {
        return {
            status: 'default',
        };
    },
    mounted() {
        const self = this;
        const node = this.getNode();
        // 监听数据改变事件
        node.on("change:data", ({ current }) => {
            // console.log('change:status', current.status)
            self.status = current.status;
        });
    },
    methods: {
        hignlightNodeEdge() {
            this.status = 'highlight';
            const graph = this.getGraph();
            const node = this.getNode();
            // console.log(node.position())
            const inComingEdges = graph.getIncomingEdges(node) || [];
            const outGoingEdges = graph.getOutgoingEdges(node) || [];
            // console.log(inComingEdges)
            // console.log(outGoingEdges)
            graph.batchUpdate(() => {
                inComingEdges.forEach((edge) => {
                    edge.attr('line/stroke', '#52c41a')
                    // edge.setZIndex(100)
                    const incomingNode = graph.getCellById(edge.source.cell)
                    incomingNode.setData({ status: 'preHighlight' });
                });
                outGoingEdges.forEach((edge) => {
                    edge.attr('line/stroke', '#1890ff')
                    // edge.attr('line/strokeWidth', 2)
                    const outgoingNode = graph.getCellById(edge.target.cell)
                    outgoingNode.setData({ status: 'highlight' });
                });
            });
            // edges.forEach((edge) => {
            //     edge.attr('line/stroke', '#1890ff')
            // });
        },
        restoreNodeEdge() {
            this.status = '';
            const graph = this.getGraph();
            const node = this.getNode();
            const edges = graph.getConnectedEdges(node);
            edges.forEach((edge) => {
                edge.attr('line/stroke', '#d1d6df')
                const incomingNode = graph.getCellById(edge.source.cell)
                incomingNode.setData({ status: '' });
                const outgoingNode = graph.getCellById(edge.target.cell)
                outgoingNode.setData({ status: '' });
                // console.log(incomingNode)
                // edge.setZIndex(1)
            });
        }
    },
};
</script>
